
package hackathon.techbooster.tanabata;

import org.json.JSONArray;
import org.json.JSONException;

import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.PointF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;

public class BambooView extends View {
    @SuppressWarnings("unused")
    private static final String TAG = BambooView.class.getSimpleName();

// @formatter:off
    private Bitmap mBase;  // 笹画像
    public Bitmap[] mTanzaku = new Bitmap[10];  // 短冊画像
    private Bitmap mRabbit;
    private JSONArray mBaseData;

    /** 表示倍率 */
    private float mRatioX = 0;
    private float mRatioY = 0;
    /** 基準とする横幅 */
    private static final float BASE_HEIGHT = 1184.0f;
    private static final float BASE_WIDTH = 720.0f;
    /** ベース表示位置 */
    private static final float BASE_X = 0f;
    private static final float BASE_Y = 0f;
    /** うさぎ表示位置 */
    private static final float RABBIT_X = 50f;
    private static final float RABBIT_Y = 60f;

    /** 短冊のリソースID */
    int[] tanzakuRes = {
            R.drawable.tanzaku_blue_text_off,
            R.drawable.tanzaku_pink_text_off,
            R.drawable.tanzaku_red_text_off,
            R.drawable.tanzaku_yellow_text_off,
            R.drawable.tanzaku_blue_text_off,
            R.drawable.tanzaku_pink_text_off,
            R.drawable.tanzaku_red_text_off,
            R.drawable.tanzaku_yellow_text_off,
            R.drawable.tanzaku_blue_text_off,
            R.drawable.tanzaku_pink_text_off
    };

    /** 書き込み済み短冊のリソースID */
    int[] tanzakuWriteRes = {
            R.drawable.tanzaku_blue_text_on,
            R.drawable.tanzaku_pink_text_on,
            R.drawable.tanzaku_red_text_on,
            R.drawable.tanzaku_yellow_text_on,
            R.drawable.tanzaku_blue_text_on,
            R.drawable.tanzaku_pink_text_on,
            R.drawable.tanzaku_red_text_on,
            R.drawable.tanzaku_yellow_text_on,
            R.drawable.tanzaku_blue_text_on,
            R.drawable.tanzaku_pink_text_on
    };

    /** 拡大短冊のリソースID */
    int[] tanzakuBigRes = {
            R.drawable.tanzaku_big_blue,
            R.drawable.tanzaku_big_pink,
            R.drawable.tanzaku_big_red,
            R.drawable.tanzaku_big_yellow,
            R.drawable.tanzaku_big_blue,
            R.drawable.tanzaku_big_pink,
            R.drawable.tanzaku_big_red,
            R.drawable.tanzaku_big_yellow,
            R.drawable.tanzaku_big_blue,
            R.drawable.tanzaku_big_pink,
    };

    /** 短冊位置 */
    PointF[] tanzakuPoint = {
            new PointF(71f,362f),
            new PointF(193f,882f),
            new PointF(373f,786f),
            new PointF(469f,150f),
            new PointF(467f,656f),
            new PointF(213f,346f),
            new PointF(329f,86f),
            new PointF(323f,426f),
            new PointF(75f,692f),
            new PointF(569f,438f),
    };

    /** 各短冊にタッチできるかどうか？のフラグ */
    boolean[] isTouch = {
            false,
            false,
            false,
            false,
            false,
            false,
            false,
            false,
            false,
            false
    };

    /** 設定用位置情報 */
    PointF[] settingsPoint = {
            new PointF(520f,970f),
            new PointF(520f,1182f),
            new PointF(670f,970f),
            new PointF(670f,1182f),
    };

    /** うさぎ表示用位置情報 */
    PointF[] rabbitPoint = {
            new PointF(32f,32f),
            new PointF(32f,138f),
            new PointF(138f,32f),
            new PointF(138f,138f),
    };
    /** うさぎ表示フラグ */
    boolean isRabbit = false;
// @formatter:on

    public BambooView(Context context, AttributeSet attrs) {
        super(context, attrs);
        setFocusable(true);
        Resources res = getResources();
        mBase = BitmapFactory.decodeResource(res, R.drawable.sasa002);
        mRabbit = BitmapFactory.decodeResource(res, R.drawable.rabbit);
        for (int cnt = 0; cnt < mTanzaku.length; cnt++) {
            mTanzaku[cnt] = BitmapFactory.decodeResource(res, tanzakuRes[cnt]);
            isTouch[cnt] = false;
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (mRatioX == 0 || mRatioY == 0) {
            // 初期化
            mRatioX = getMeasuredWidth() / BASE_WIDTH;
            mRatioY = getMeasuredHeight() / BASE_HEIGHT;
        }
        // Canvasの状態を保存しておいて、画面サイズにfitするように拡大(または縮小)
        canvas.save();
        canvas.scale(mRatioX, mRatioY);
        canvas.drawARGB(255, 0, 0, 0);

        canvas.drawBitmap(mBase, BASE_X, BASE_Y, null);
        for (int cnt = 0; cnt < mTanzaku.length; cnt++) {
            canvas.drawBitmap(mTanzaku[cnt], tanzakuPoint[cnt].x, tanzakuPoint[cnt].y, null);
        }

        if (isRabbit) {
            canvas.drawBitmap(mRabbit, RABBIT_X, RABBIT_Y, null);
        }

        canvas.save();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // タッチ座標 → 基準座標系(幅480pixelとした場合の座標)
        float x = event.getX() / mRatioX;
        float y = event.getY() / mRatioY;

        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            int idx = checkTanzaku(x, y);
            if (idx == -1) {
                checkObject(x, y);
            } else {

                try {
                    String id = mBaseData.getJSONObject(idx).getString(PreferenceUtils.JSON_ID);
                    String name = mBaseData.getJSONObject(idx).getString(PreferenceUtils.JSON_NAME);
                    String hope = mBaseData.getJSONObject(idx).getString(PreferenceUtils.JSON_HOPE);

                    Intent i = new Intent(getContext(), DetailActivity.class);
                    i.putExtra(PreferenceUtils.KEY_ID, id);
                    i.putExtra(PreferenceUtils.KEY_NAME, name);
                    i.putExtra(PreferenceUtils.KEY_HOPE, hope);
                    i.putExtra(PreferenceUtils.KEY_BACK_RES, tanzakuBigRes[idx]);
                    getContext().startActivity(i);
                } catch (JSONException e) {
                    Toast.makeText(getContext(), R.string.error_data_format, Toast.LENGTH_SHORT)
                            .show();
                }
            }
        }
        return false;
    }

    protected void setBitmap(int id) {
        setBitmap(id, true);
    }

    /**
     * 短冊の設定
     * 
     * @param idx 対象の短冊のIndex
     * @param flag 書き込み済み短冊かどうか
     */
    protected void setBitmap(int idx, boolean flag) {
        Resources res = getResources();
        if (flag) {
            mTanzaku[idx] = BitmapFactory.decodeResource(res, tanzakuWriteRes[idx]);
        } else {
            mTanzaku[idx] = BitmapFactory.decodeResource(res, tanzakuRes[idx]);
        }
        isTouch[idx] = flag;
    }

    protected void setBaseData(JSONArray baseData) {
        mBaseData = baseData;
    }

    protected int checkTanzaku(float x, float y) {
        for (int cnt = 0; cnt < mTanzaku.length; cnt++) {
            // 書き込み短冊の場合のみチェック
            if (isTouch[cnt]) {
                PointF touchPoint = new PointF(x, y);
                PointF leftTop = tanzakuPoint[cnt];
                PointF leftBottom = new PointF(leftTop.x, leftTop.y + mTanzaku[cnt].getHeight());
                PointF rightTop = new PointF(leftTop.x + mTanzaku[cnt].getWidth(), leftTop.y);
                PointF rightBottom = new PointF(leftTop.x + mTanzaku[cnt].getWidth(), leftTop.y
                        + mTanzaku[cnt].getHeight());
                PointF checkPoint = new PointF(leftTop.x + mTanzaku[cnt].getWidth() / 2, leftTop.y
                        + mTanzaku[cnt].getHeight() / 2);

                if (!intersect(leftTop, leftBottom, touchPoint, checkPoint)
                        && !intersect(leftTop, rightTop, touchPoint, checkPoint)
                        && !intersect(leftBottom, rightBottom, touchPoint, checkPoint)
                        && !intersect(rightTop, rightBottom, touchPoint, checkPoint)) {
                    return cnt;
                }
            }
        }
        return -1;
    }

    private boolean intersect(PointF p1, PointF p2, PointF p3, PointF p4) {
        return !(((p1.x - p2.x) * (p3.y - p1.y) + (p1.y - p2.y) * (p1.x - p3.x))
                * ((p1.x - p2.x) * (p4.y - p1.y) + (p1.y - p2.y) * (p1.x - p4.x)) > 0);
    }

    private void checkObject(float x, float y) {
        PointF touchPoint = new PointF(x, y);
        PointF rabbitCheckPoint = new PointF((rabbitPoint[2].x + rabbitPoint[0].x) / 2f,
                (rabbitPoint[1].y + rabbitPoint[0].y) / 2f);

        // うさぎ表示チェック
        if (!intersect(rabbitPoint[0], rabbitPoint[1], touchPoint, rabbitCheckPoint)
                && !intersect(rabbitPoint[0], rabbitPoint[2], touchPoint, rabbitCheckPoint)
                && !intersect(rabbitPoint[1], rabbitPoint[3], touchPoint, rabbitCheckPoint)
                && !intersect(rabbitPoint[2], rabbitPoint[3], touchPoint, rabbitCheckPoint)) {
            isRabbit = !isRabbit;
            invalidate();
        }

    }

    public boolean isSettings(MotionEvent event) {
        PointF touchPoint = new PointF(event.getX() / mRatioX, event.getY() / mRatioY);
        PointF settingsCheckPoint = new PointF((settingsPoint[2].x + settingsPoint[0].x) / 2f,
                (settingsPoint[1].y + settingsPoint[0].y) / 2f);

        // セッティング表示チェック
        if (!intersect(settingsPoint[0], settingsPoint[1], touchPoint, settingsCheckPoint)
                && !intersect(settingsPoint[0], settingsPoint[2], touchPoint, settingsCheckPoint)
                && !intersect(settingsPoint[1], settingsPoint[3], touchPoint, settingsCheckPoint)
                && !intersect(settingsPoint[2], settingsPoint[3], touchPoint, settingsCheckPoint)) {
            return true;
        } else {
            return false;
        }
    }
    
    public void clear() {
        Resources res = getResources();
        for (int cnt = 0; cnt < mTanzaku.length; cnt++) {
            mTanzaku[cnt] = BitmapFactory.decodeResource(res, tanzakuRes[cnt]);
            isTouch[cnt] = false;
        }
    }
}
